package org.zebra.mybatis.plus.druid;

import cn.hutool.core.text.CharSequenceUtil;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.zebra.common.core.GeneralYmlPropertySourceFactory;

import java.util.Map;
import java.util.Set;

/**
 * @author zhanghongbin
 */
public class DruidMonitorPostProcessor implements EnvironmentPostProcessor {

    private Log log;

    /**
     * 使用 DeferredLog 输出日志，因为日志组件还没有初始化
     *
     * @param deferredLogFactory 对象
     */
    public DruidMonitorPostProcessor(DeferredLogFactory deferredLogFactory) {
        log = deferredLogFactory.getLog(DruidMonitorPostProcessor.class);
    }

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {

        String monitorEnabledConfig = environment.getProperty("zebra.database.monitor.enabled");
        boolean monitorEnabled = true;
        if (!CharSequenceUtil.isBlank(monitorEnabledConfig)) {
            monitorEnabled = Boolean.parseBoolean(monitorEnabledConfig);
        }
        // 慢sql时间
        String slowSqlMillisConfig = environment.getProperty("zebra.database.monitor.slow-sql-millis");
        Integer slowSqlMillis = null;
        if (!CharSequenceUtil.isBlank(slowSqlMillisConfig)) {
            slowSqlMillis = Integer.parseInt(slowSqlMillisConfig);
        }
        if (!monitorEnabled) {
            return;
        }
        String port = environment.getProperty("server.port", "8080");
        String contextPath = environment.getProperty("server.servlet.context-path", "");
        log.info("druid web console http://localhost:" + port + contextPath + "/druid");

        String aopPatterns = environment.getProperty("zebra.database.monitor.aop-patterns");
        Resource resource = new ClassPathResource("druid-springboot.yml");
        // 加载成PropertySource对象，并添加到Environment环境中
        GeneralYmlPropertySourceFactory generalYmlPropertySourceFactory = new GeneralYmlPropertySourceFactory();
        PropertiesPropertySource propertySource = generalYmlPropertySourceFactory.load(resource);
        Map<String, Object> sourceMap = propertySource.getSource();
        if (!CharSequenceUtil.isBlank(aopPatterns)) {
            sourceMap.put("spring.datasource.druid.aop-patterns", aopPatterns);
        } else {
            Set<Object> sourcesSet = application.getAllSources();
            if (!sourcesSet.isEmpty()) {
                try {
                    Class cls = (Class) sourcesSet.iterator().next();
                    sourceMap.put("spring.datasource.druid.aop-patterns", cls.getPackage() + ".*");
                } catch (Exception e) {

                }
            }
        }
        sourceMap.put("spring.datasource.druid.filter.slf4j.enabled", monitorEnabled);
        sourceMap.put("spring.datasource.druid.stat-view-servlet.enabled", monitorEnabled);
        String userName = environment.getProperty("zebra.database.monitor.username", "");
        String password = environment.getProperty("zebra.database.monitor.password", "");
        if (!userName.isEmpty() && !password.isEmpty()) {
            sourceMap.put("spring.datasource.druid.stat-view-servlet.login-username", userName);
            sourceMap.put("spring.datasource.druid.stat-view-servlet.login-password", password);
        }
        // 可以访问的ip，没有配置则不进行限制
        String allow = environment.getProperty("zebra.database.monitor.allow", "");
        if (!allow.isEmpty()) {
            sourceMap.put("spring.datasource.druid.stat-view-servlet.allow", allow);
        }
        sourceMap.put("spring.datasource.druid.web-stat-filter.enabled", monitorEnabled);
        if (slowSqlMillis != null) {
            sourceMap.put("spring.datasource.druid.filter.stat.slow-sql-millis", slowSqlMillis);
            sourceMap.put("spring.datasource.druid.filter.stat.logSlowSql", true);
            sourceMap.put("spring.datasource.druid.filter.stat.enabled", true);
        }
        environment.getPropertySources().addLast(propertySource);
    }
}
